package config

import (
	"errors"
	"fmt"
	"gitee.com/worklz/yunj-blog-go-micro-common/jaeger"
	"gitee.com/worklz/yunj-blog-go-micro-common/log"
	"gitee.com/worklz/yunj-blog-go-micro-common/mysql"
	"gitee.com/worklz/yunj-blog-go-micro-common/redis"
	"gitee.com/worklz/yunj-blog-go-micro-common/util"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

var FilePath = "config/config.yaml"

// InitConfig 初始化配置
func InitConfig(c any) {
	// viper文件配置
	viper.SetConfigType("yaml")
	viper.SetConfigFile(FilePath)

	// 读取配置
	if err := viper.ReadInConfig(); err != nil {
		panic("配置文件内容读取错误！")
	}

	// 监听配置文件
	viper.WatchConfig()
	// 添加方法监听配置文件更改处理
	viper.OnConfigChange(func(in fsnotify.Event) {
		if err := toConfig(c); err != nil {
			log.Error("配置文件修改后报错了！", err)
		}
	})

	// 将配置文件内容写入到结构体
	if err := toConfig(c); err != nil {
		panic(err.Error())
	}

}

// 将配置文件内容写入到结构体
func toConfig(c any) error {
	// 判断是否为结构体
	if ok := util.IsStruct(c); !ok {
		return errors.New("初始化配置文件需传入结构体或指向结构体的指针类型变量")
	}
	// 将配置文件内容写入到结构体
	if err := viper.Unmarshal(&c); err != nil {
		return fmt.Errorf("配置文件内容写入结构体错误！%v", err)
	}
	// jaeger配置映射
	if ok := viper.IsSet("jaeger"); ok {
		if err := viper.UnmarshalKey("jaeger", &jaeger.Config); err != nil {
			return fmt.Errorf("jaeger配置文件内容写入结构体错误！%v", err)
		}
	}
	// redis配置映射
	if ok := viper.IsSet("redis"); ok {
		if err := viper.UnmarshalKey("redis", &redis.Config); err != nil {
			return fmt.Errorf("redis配置文件内容写入结构体错误！%v", err)
		}
	}
	// mysql配置映射
	if ok := viper.IsSet("mysql"); ok {
		if err := viper.UnmarshalKey("mysql", &mysql.Config); err != nil {
			return fmt.Errorf("mysql配置文件内容写入结构体错误！%v", err)
		}
	}

	return nil
}
